package com.treasure.mall.biz.entity.order;

import com.treasure.mall.biz.entity.Base2PO;
import com.treasure.mall.biz.entity.user.MerchantPO;
import com.treasure.mall.zbq.common.constant.Constant;
import com.treasure.mall.zbq.common.ienum.order.OrderEnums;
import lombok.Getter;
import lombok.Setter;

import javax.persistence.*;
import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Comparator;
import java.util.List;

/**
 * 子订单，店铺订单
 *
 * @author allan
 * @version 1.0.0
 * @date 2020/6/11
 */
@Entity
@Table(name = "zb_sub_order")
@Setter
@Getter
@Cacheable(false)
public class SubOrderPO extends Base2PO {
    @Id
    @Column(name = "id", length = 30)
    private String subOrderId;
    @ManyToOne
    @JoinColumn(name = "rel_order_id", foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
    private DealOrderPO orderPO;
    @ManyToOne
    @JoinColumn(name = "rel_merchant_id", foreignKey = @ForeignKey(value = ConstraintMode.NO_CONSTRAINT))
    private MerchantPO merchantPO;
    @Column(name = "order_status")
    private OrderEnums.Status status;
    /**
     * 商品数量
     */
    @Column(name = "goods_num")
    private int goodsNum;
    /**
     * 最终金额
     */
    @Column(name = "final_amount", scale = 2, precision = 10)
    private BigDecimal finalAmount;
    /**
     * 已经抵扣的钱（比如拍卖的保证金）
     */
    @Column(name = "deduct_amount", scale = 2, precision = 10)
    private BigDecimal deductAmount;
    /**
     * 商品金额
     */
    @Column(name = "goods_amount", scale = 2, precision = 10)
    private BigDecimal goodsAmount;
    /**
     * 运费
     */
    @Column(name = "freight_amount", scale = 2, precision = 9)
    private BigDecimal freightAmount;
    /**
     * 优惠金额
     */
    @Column(name = "pmt_amount", scale = 2, precision = 9)
    private BigDecimal pmtAmount;
    /**
     * 鉴定服务费
     */
    private BigDecimal identifyFee;
    /**
     * 预计结算时间
     */
    @Column(name = "settlement_time", columnDefinition = Constant.DATE_COLUMN_DEFINITION)
    private LocalDateTime settlementTime;
    /**
     * 最迟收获时间，自动签收
     */
    @Column(name = "last_received_time", columnDefinition = Constant.DATE_COLUMN_DEFINITION)
    private LocalDateTime lastReceivedTime;
    /**
     * 直播场次
     */
    @Column(name = "live_session_id")
    private String liveSessionId;
    @Column(name = "auction_session_id")
    private Long auctionSessionId;
    @Column(name = "order_type")
    private OrderEnums.OrderType orderType;
    /**
     * 物流状态
     * {@link com.treasure.mall.zbq.common.ienum.order.OrderEnums.DeliverStatus}
     */
    @Transient
    private OrderEnums.DeliverStatus deliverStatus;

    @OneToMany(mappedBy = "subOrderPO", fetch = FetchType.EAGER, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}, orphanRemoval = true)
    private List<OrderItemPO> orderItemPOS;

    /**
     * 用户附言
     */
    @Column(name = "memo")
    private String memo;
    /**
     * 订单备注
     */
    @Column(name = "remark")
    private String remark;
    /**
     * 是否转正
     */
    @Column(name = "amount_done")
    private boolean amountDone;
    /**
     * 付款单编号
     */
    @Column(name = "payment_bill_id")
    protected String paymentBillId;

    public OrderEnums.DeliverStatus getDeliverStatus() {
        return orderItemPOS.get(0).getDeliverStatus();
    }

    public boolean isReceived() {
        return orderItemPOS.stream().allMatch(p -> p.getDeliverStatus() == OrderEnums.DeliverStatus.RECEIVED);
    }

    /**
     * 得到最新的签收时间
     *
     * @return
     */
    public LocalDateTime receivedTime() {
        return orderItemPOS.stream()
                .filter(p -> p.getDeliverStatus() == OrderEnums.DeliverStatus.RECEIVED)
                .max(Comparator.comparing(OrderItemPO::getReceiveTime))
                .map(OrderItemPO::getReceiveTime).orElse(null);
    }

    public boolean isAfterSale() {
        return this.orderItemPOS.stream().anyMatch(OrderItemPO::isAfterSale);
    }

    public boolean isOrderClose() {
        return this.orderItemPOS.stream().allMatch(p -> p.getAfterSaleStatus() == OrderEnums.AfterSaleStatus.COMPLETE_APPLY);
    }

    public BigDecimal fatherRebate() {
        return orderItemPOS.stream()
                .map(OrderItemPO::getFatherRebate).reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    public BigDecimal grantRebate() {
        return orderItemPOS.stream()
                .map(OrderItemPO::getGrandRebate).reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    public BigDecimal payment() {
        return orderItemPOS.stream()
                .map(OrderItemPO::getPayment).reduce(BigDecimal.ZERO, BigDecimal::add);
    }

    public boolean enableDeliver() {
        return getDeliverStatus() == OrderEnums.DeliverStatus.TO_DELIVER && this.orderPO.getPayStatus() == OrderEnums.PayStatus.PAYED;
    }

    /**
     * 是否可支付
     *
     * @return
     */
    public boolean enablePay() {
        return (this.orderPO.getPayStatus() == OrderEnums.PayStatus.TO_PAY || this.orderPO.getPayStatus() == OrderEnums.PayStatus.FAILED) &&
                this.status == OrderEnums.Status.ACTIVE;
    }

    /**
     * 是否可确认收货
     *
     * @return
     */
    public boolean enableReceived() {
        return orderItemPOS.stream().allMatch(p -> p.getDeliverStatus() == OrderEnums.DeliverStatus.USER_TO_RECEIVE);
    }

    /**
     * 显示售后状态
     *
     * @return
     */
    public OrderEnums.AfterSaleStatus showAfterStatus() {
        if (orderItemPOS.stream().anyMatch(p -> p.getAfterSaleStatus() != null)) {
            return orderItemPOS.get(0).getAfterSaleStatus();
        }
        return null;
    }

    /**
     * 适用于前端显示的订单状态
     *
     * @return
     */
    public OrderEnums.UserOrderStatus userOrderStatus() {
        if (enablePay()) {
            return OrderEnums.UserOrderStatus.TO_PAY;
        }
        if (orderItemPOS.stream().anyMatch(p -> p.getAfterSaleStatus() != null)) {
            return OrderEnums.UserOrderStatus.AFTER_SALE_ING;
        }
        if (enableDeliver()) {
            return OrderEnums.UserOrderStatus.TO_DELIVER;
        }
        if (enableReceived()) {
            return OrderEnums.UserOrderStatus.TO_RECEIVE;
        }

        if (getDeliverStatus().getCode().equals(OrderEnums.DeliverStatus.RECEIVED.getCode())) {
            return OrderEnums.UserOrderStatus.RECEIVED;
        }

        return null;
    }

    public BigDecimal refundTotalAmount() {
        if (orderItemPOS == null || orderItemPOS.size() == 0) {
            return BigDecimal.ZERO;
        }
        BigDecimal refundAmount = BigDecimal.ZERO;
        for (OrderItemPO item : orderItemPOS) {
            refundAmount = refundAmount.add(item.refundAmount());
        }
        return refundAmount;
    }

    public boolean isCanConverted() {
        return this.orderItemPOS.stream().anyMatch(OrderItemPO::isCanConverted);
    }
}
